﻿using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System;
using System.Data.Entity;
using System.Data;

namespace RepoInfrastructure
{
	public class ContextReadonlyRepository<T, TContext> : IReadonlyRepository<T>
		where T : class
        where TContext : DbContext
	{
        protected DbContext Context = null;
        protected bool shareContext = false;

        public ContextReadonlyRepository()
        {
            Context = FastActivator.Create<TContext>();
        }

        public ContextReadonlyRepository(DbContext context)
        {
            Context = context;
            shareContext = true;
        }

        protected DbSet<T> DbSet
        {
            get
            {
                return Context.Set<T>();
            }
        }

        public void Dispose()
        {
            if (shareContext && (Context != null))
                Context.Dispose();
        }

        public virtual IQueryable<T> All
        {
            get { return DbSet.AsQueryable(); }
        }

        public virtual IQueryable<T> Filter(Expression<Func<T, bool>> predicate)
        {
            return DbSet.Where(predicate).AsQueryable();
        }

        public virtual IQueryable<T> Filter(Expression<Func<T, bool>> filter, out int total, int index = 0, int size = 50)
        {
            int skipCount = index * size;
            var _resetSet = filter != null ? DbSet.Where(filter).AsQueryable() : 
				DbSet.AsQueryable();
            _resetSet = skipCount == 0 ? _resetSet.Take(size) : 
				_resetSet.Skip(skipCount).Take(size);
            total = _resetSet.Count();
            return _resetSet.AsQueryable();
        }

        public bool Contains(Expression<Func<T, bool>> predicate)
        {
            return DbSet.Count(predicate) > 0;
        }

        public virtual T Find(params object[] keys)
        {
            return DbSet.Find(keys);
        }

        public virtual T Find(Expression<Func<T, bool>> predicate)
        {
            return DbSet.FirstOrDefault(predicate);
        }

        public virtual int Count
        {
            get
            {
                return DbSet.Count();
            }
        }
    }

}